package com.hezhiqin.formework.beans.support;

import com.hezhiqin.formework.beans.config.HZQBeanDefinition;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

/**
 * @program: homeWork
 * @description:
 * @author: hezhiqin
 * @create: 2019-10-28 12:40
 */
public class HZQBeanDefinitionReader {


    //保存扫描的所有的类名
    private List<String> registyBeanClasses = new ArrayList<String>();

    //获取配置信息，定位到需要扫描的包下面
    Properties configContext = new Properties();


    private  final String  SCAN_PACKGE = "scanPackage";


    /**
     * @author: hezhiqin
     * @date: 2022/1/13 16:19
     * @description: 读取配置文件
     * @param:
     * @return:
     */

    public HZQBeanDefinitionReader (String... locations){
        InputStream  is = this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:",""));
        try {
            configContext.load(is);
            doScanner(configContext.getProperty(SCAN_PACKGE));
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (is!=null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }



    //把配置文件中扫描到的所有的配置信息转换为GPBeanDefinition对象，以便于之后IOC操作方便
    public List<HZQBeanDefinition> loadBeanDefinitions() throws ClassNotFoundException {


        List<HZQBeanDefinition>  result = new ArrayList<HZQBeanDefinition>();

        for (String  registyBeanClass: registyBeanClasses) {

            Class<?> beanClass = Class.forName(registyBeanClass);
            //如果是一个接口，是不能实例化的
            //用它实现类来实例化
            if(beanClass.isInterface()) { continue; }


            //beanName有三种情况:
            //1、默认是类名首字母小写
            //2、自定义名字
            //3、接口注入
            result.add(doCreateBeanDefintion(toLowerFirstCase(beanClass.getSimpleName()),beanClass.getName()));
//                result.add(doCreateBeanDefinition(beanClass.getName(),beanClass.getName()));

            Class<?> [] interfaces = beanClass.getInterfaces();
            for (Class<?> i : interfaces) {
                //如果是多个实现类，只能覆盖
                //为什么？因为Spring没那么智能，就是这么傻
                //这个时候，可以自定义名字
                result.add(doCreateBeanDefintion(i.getSimpleName(),beanClass.getName()));
            }


        }



        return result;
    }


    public Properties getConfigContext() {
        return configContext;
    }





    /**
     * @param scanPackage
     * 扫描配置的路径，将所有相关的类放入容器中
     */
    private void doScanner(String scanPackage) {

        //scanPackage = com.hezhiqin ，存储的是包路径
        //转换为文件路径，实际上就是把.替换为/就 OK 了
        URL url = this.getClass().getClassLoader().getResource("/" +
                scanPackage.replaceAll("\\.","/"));//将扫描的包的.换成/
        File classDir = new File(url.getFile());
        for (File file : classDir.listFiles()) {
            if (file.isDirectory()) {//如果是一个文件
                doScanner(scanPackage + "." +file.getName());
            }else {
                if(!file.getName().endsWith(".class")){continue;}//不是一个class文件则跳过
                String clazzName = (scanPackage + "." + file.getName().replace(".class",""));//获取classpath
                //
                registyBeanClasses.add(clazzName);

            }
        }


    }



    //吧每一个配置信息解析成为BeanDefintion
    private  HZQBeanDefinition doCreateBeanDefintion(String factoryBeanName,String beanClassName){
        HZQBeanDefinition hzqBeanDefinition = new HZQBeanDefinition();
        hzqBeanDefinition.setBeanClassName(beanClassName);
        hzqBeanDefinition.setFactoryBeanName(factoryBeanName);
        return  hzqBeanDefinition;
    }



    private String toLowerFirstCase(String simpleName) {
        char [] chars = simpleName.toCharArray();
        //之所以加，是因为大小写字母的 ASCII 码相差 32，
        // 而且大写字母的 ASCII 码要小于小写字母的 ASCII 码
        //在 Java 中，对 char 做算学运算，实际上就是对 ASCII 码做算学运算
        if (isUpperCase(chars[0])) {
            chars[0] += 32;
        }
        return String.valueOf(chars);

    }


    /*
     * 是否是大写
     */
    public boolean isUpperCase(char c) {
        return c >=65 && c <= 90;
    }
}
